package com.jwgf.fault;

import com.jwgf.fram.FramManager;
import com.jwgf.objectbox.CbfFaultRecord;
import com.jwgf.objectbox.DofferFaultRecord;
import com.jwgf.objectbox.FaultRecord;
import com.jwgf.objectbox.HeadFaultCounter;
import com.jwgf.objectbox.HeadFaultCounter_;
import com.jwgf.objectbox.HeadFaultRecord;
import com.jwgf.objectbox.ObjectBox;
import com.jwgf.objectbox.ProcessRecord;
import com.jwgf.objectbox.RedLightRecord;
import com.jwgf.objectbox.SpindleRecord;
import com.jwgf.report.ShiftTimeRule;
import com.jwgf.smarowindingmachine_unity.logic.DatabaseChangedEvent.CBFFaultChanged;
import com.jwgf.smarowindingmachine_unity.logic.DatabaseChangedEvent.DoffFaultChanged;
import com.jwgf.smarowindingmachine_unity.logic.DatabaseChangedEvent.FaultChanged;
import com.jwgf.smarowindingmachine_unity.logic.DatabaseChangedEvent.MachineFaultChanged;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;

import io.objectbox.Box;

public class FaultRecorder {
    private static FaultRecorder instance = new FaultRecorder();
    private FramManager fm = FramManager.getInstance();
    private HashMap<Integer, FaultContent> faultMap;
    private HashMap<Integer, Long> curFaultIdMap = new HashMap<Integer, Long>();
    public static final int FAULT_TYPE = 0;//故障
    public static final int PROCESS_TYPE = 1;//工艺
    public static final int RED_LIGHT_TYPE = 2;//红灯
    public static final int MACHINE_FAULT_TYPE = 4;//整机
    public static final int CBF_FAULT_TYPE = 5;//tPLC 故障
    public static final int DOFF_FAULT_TYPE = 6;// CAN转485

    private FaultRecorder() {

    }

    public static FaultRecorder getInstance() {
        return instance;
    }

    public void setFaultMap(HashMap<Integer, FaultContent> faultMap) {
        this.faultMap = faultMap;
    }

    public HashMap<Integer, FaultContent> getFaultMap() {
        return faultMap;
    }

    public synchronized void startFaultRecord(final int type, final int faultCode) {
        switch (type) {
            case RED_LIGHT_TYPE: {
                Box<RedLightRecord> box = ObjectBox.get().boxFor(RedLightRecord.class);
                long start = Calendar.getInstance().getTimeInMillis();
                RedLightRecord record = new RedLightRecord(faultCode, start);
                long id = box.put(record);
                curFaultIdMap.put(faultCode, id);
                Box<SpindleRecord> spindleBox = ObjectBox.get().boxFor(SpindleRecord.class);
                spindleBox.put(new SpindleRecord(faultCode, start));
                EventBus.getDefault().post(new FaultChanged());
            }
            break;
            case PROCESS_TYPE: {
                Box<ProcessRecord> box = ObjectBox.get().boxFor(ProcessRecord.class);
                long start = Calendar.getInstance().getTimeInMillis();
                ProcessRecord record = new ProcessRecord(faultCode, start);
                long id = box.put(record);
                curFaultIdMap.put(faultCode, id);
                Box<SpindleRecord> spindleBox = ObjectBox.get().boxFor(SpindleRecord.class);
                spindleBox.put(new SpindleRecord(faultCode, start));
                EventBus.getDefault().post(new FaultChanged());
            }
            break;
            case FAULT_TYPE: {
                Box<FaultRecord> box = ObjectBox.get().boxFor(FaultRecord.class);
                long start = Calendar.getInstance().getTimeInMillis();
                FaultRecord record = new FaultRecord(faultCode, start);
                long id = box.put(record);
                curFaultIdMap.put(faultCode, id);
                Box<SpindleRecord> spindleBox = ObjectBox.get().boxFor(SpindleRecord.class);
                spindleBox.put(new SpindleRecord(faultCode, start));
                EventBus.getDefault().post(new FaultChanged());
            }
            break;
            case MACHINE_FAULT_TYPE: {
                saveHeadFaultCounter(faultCode);
                Box<HeadFaultRecord> box = ObjectBox.get().boxFor(HeadFaultRecord.class);
                HeadFaultRecord record = new HeadFaultRecord(faultCode, Calendar.getInstance().getTimeInMillis());
                long id = box.put(record);
                curFaultIdMap.put(faultCode, id);
                EventBus.getDefault().post(new MachineFaultChanged());
            }
            break;
            case CBF_FAULT_TYPE: {
                Box<CbfFaultRecord> box = ObjectBox.get().boxFor(CbfFaultRecord.class);
                CbfFaultRecord record = new CbfFaultRecord(faultCode, Calendar.getInstance().getTimeInMillis());
                long id = box.put(record);
                curFaultIdMap.put(faultCode, id);
                EventBus.getDefault().post(new CBFFaultChanged());
            }
            break;
            case DOFF_FAULT_TYPE: {
                Box<DofferFaultRecord> box = ObjectBox.get().boxFor(DofferFaultRecord.class);
                DofferFaultRecord record = new DofferFaultRecord(faultCode, Calendar.getInstance().getTimeInMillis());
                long id = box.put(record);
                curFaultIdMap.put(faultCode, id);
                EventBus.getDefault().post(new DoffFaultChanged());
            }
            break;
            default:
                break;
        }
    }


    public synchronized void stopFaultRecord(final int type, final int faultCode) {
        switch (type) {
            case RED_LIGHT_TYPE:
                if (curFaultIdMap.containsKey(faultCode)) {
                    long id = curFaultIdMap.remove(faultCode);
                    Box<RedLightRecord> box = ObjectBox.get().boxFor(RedLightRecord.class);
                    RedLightRecord record = box.get(id);
                    long end = Calendar.getInstance().getTimeInMillis();
                    record.setEnd(end);
                    long duration = record.getEnd() - record.getStart();
                    if (duration > 0) {
                        record.setDuration(duration);
                    }
                    box.put(record);
                }
                break;
            case PROCESS_TYPE:
                if (curFaultIdMap.containsKey(faultCode)) {
                    long id = curFaultIdMap.remove(faultCode);
                    Box<ProcessRecord> box = ObjectBox.get().boxFor(ProcessRecord.class);
                    ProcessRecord record = box.get(id);
                    long end = Calendar.getInstance().getTimeInMillis();
                    record.setEnd(end);
                    long duration = record.getEnd() - record.getStart();
                    if (duration > 0) {
                        record.setDuration(duration);
                    }
                    box.put(record);

                }
                break;
            case FAULT_TYPE:
                if (curFaultIdMap.containsKey(faultCode)) {
                    long id = curFaultIdMap.remove(faultCode);
                    Box<FaultRecord> box = ObjectBox.get().boxFor(FaultRecord.class);
                    FaultRecord record = box.get(id);
                    long end = Calendar.getInstance().getTimeInMillis();
                    record.setEnd(end);
                    long duration = record.getEnd() - record.getStart();
                    if (duration > 0) {
                        record.setDuration(duration);
                    }
                    box.put(record);

                }
                break;
            case MACHINE_FAULT_TYPE:
                if (curFaultIdMap.containsKey(faultCode)) {
                    long id = curFaultIdMap.remove(faultCode);
                    Box<HeadFaultRecord> box = ObjectBox.get().boxFor(HeadFaultRecord.class);
                    HeadFaultRecord record = box.get(id);
                    long end = Calendar.getInstance().getTimeInMillis();
                    record.setEnd(end);
                    long duration = record.getEnd() - record.getStart();
                    if (duration > 0) {
                        record.setDuration(duration);
                    }
                    box.put(record);
                }
                break;
            case CBF_FAULT_TYPE:
                if (curFaultIdMap.containsKey(faultCode)) {
                    long id = curFaultIdMap.remove(faultCode);
                    Box<CbfFaultRecord> box = ObjectBox.get().boxFor(CbfFaultRecord.class);
                    CbfFaultRecord record = box.get(id);
                    long end = Calendar.getInstance().getTimeInMillis();
                    record.setEnd(end);
                    long duration = record.getEnd() - record.getStart();
                    if (duration > 0) {
                        record.setDuration(duration);
                    }
                    box.put(record);
                }
                break;
            case DOFF_FAULT_TYPE:
                if (curFaultIdMap.containsKey(faultCode)) {
                    long id = curFaultIdMap.remove(faultCode);
                    Box<DofferFaultRecord> box = ObjectBox.get().boxFor(DofferFaultRecord.class);
                    DofferFaultRecord record = box.get(id);
                    long end = Calendar.getInstance().getTimeInMillis();
                    record.setEnd(end);
                    long duration = record.getEnd() - record.getStart();
                    if (duration > 0) {
                        record.setDuration(duration);
                    }
                    box.put(record);
                }
                break;

            default:
                break;
        }

    }

    public String getFault(int faultCode) {
        FaultContent content = faultMap.get(faultCode);
        if (content == null) {
            return String.valueOf(faultCode);
        }
        return faultMap.get(faultCode).getName();
    }

    private void saveHeadFaultCounter(int faultCode) {
        Box<HeadFaultCounter> box = ObjectBox.get().boxFor(HeadFaultCounter.class);
        HeadFaultCounter counter = box.query()
                .equal(HeadFaultCounter_.start, Long.parseLong(ShiftTimeRule.getInstance().getCurrentShiftStartTime()))
                .build().findFirst();
        if (counter == null) {
            counter = new HeadFaultCounter();
            counter.start = Long.parseLong(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        }
        int address = (faultCode & 0x00ffff00) >> 8;
        int bit = faultCode & 0xf;
        if (address == 252) {
            switch (bit) {
                case 1:
                    counter.counter_252_1++;
                    break;
                case 2:
                    counter.counter_252_2++;
                    break;
                case 4:
                    counter.counter_252_4++;
                    break;
                case 6:
                    counter.counter_252_6++;
                    break;
                case 7:
                    counter.counter_252_7++;
                    break;
                case 8:
                    counter.counter_252_8++;
                    break;
                case 9:
                    counter.counter_252_9++;
                    break;
                case 10:
                    counter.counter_252_10++;
                    break;
                case 11:
                    counter.counter_252_11++;
                    break;
                case 12:
                    counter.counter_252_12++;
                    break;
                case 13:
                    counter.counter_252_13++;
                    break;
                case 14:
                    counter.counter_252_14++;
                    break;

            }

        } else if (address == 254) {
            switch (bit) {
                case 0:
                    counter.counter_254_0++;
                    break;
                case 1:
                    counter.counter_254_1++;
                    break;
                case 2:
                    counter.counter_254_2++;
                    break;
                case 8:
                    counter.counter_254_8++;
                    break;
                case 9:
                    counter.counter_254_9++;
                    break;
                case 10:
                    counter.counter_254_10++;
                    break;
                case 11:
                    counter.counter_254_11++;
                    break;
                case 12:
                    counter.counter_254_12++;
                    break;
                case 13:
                    counter.counter_254_13++;
                    break;
                case 14:
                    counter.counter_254_14++;
                    break;
                case 15:
                    counter.counter_254_15++;
                    break;
            }
        }
        box.put(counter);
    }

}
